package cn.shujuhai.cms.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.shujuhai.cms.domain.GroupRecipient;
import cn.shujuhai.cms.domain.Recipient;
import cn.shujuhai.cms.mapper.RecipientMapper;
import cn.shujuhai.cms.service.GroupRecipientService;
import cn.shujuhai.cms.service.RecipientService;
import cn.shujuhai.common.pluging.data.ResultCode;
import cn.shujuhai.common.pluging.data.ResultVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author niuyahu
 * @description 针对表【recipient】的数据库操作Service实现
 * @createDate 2024-12-25 14:58:58
 */
@Service
@RequiredArgsConstructor
public class RecipientServiceImpl extends ServiceImpl<RecipientMapper, Recipient>
        implements RecipientService {
    final GroupRecipientService groupRecipientService;
    private static final List<Recipient> repeatList = new ArrayList<>();

    /**
     * 分页查询系统收件人组信息
     *
     * @param email    收件人邮箱（可为null，不为null时进行模糊查询）
     * @param page     当前页码（从1开始）
     * @param pageSize 每页显示的记录数
     * @return 返回包含分页信息和系统收件人列表的ResultVo对象，其中PageInfo<Recipient>包含了分页的详细信息，如总记录数、总页数等
     */
    @Override
    public ResultVo<PageInfo<Recipient>> getRecipientPageInfo(String email, Integer page, Integer pageSize, Long groupId) {
        PageHelper.startPage(page, pageSize);
        var wrapper = getRecipientListByGroupId(groupId);
        if (email != null && !email.isEmpty()) {
            wrapper.like("email", email);
        }
        List<Recipient> recipientList = this.list(wrapper.orderByDesc(Recipient::getId));  // 根据用户Id降序排序
        PageInfo<Recipient> recipientPageInfo = new PageInfo<>(recipientList);
        return ResultVo.success(recipientPageInfo);
    }

    /**
     * 新增收件人对象
     *
     * @param recipient 收件人对象
     * @return 新增成功或失败的响应状态
     */
    @Override
    public ResultVo<?> add(Recipient recipient) {
        if (!this.save(recipient)) {
            return ResultVo.failure(ResultCode.FAILED);
        }
        GroupRecipient groupRecipient = new GroupRecipient();
        groupRecipient.setGroupId(recipient.getGroupId());
        groupRecipient.setRecipientId(recipient.getId());
        if (!this.groupRecipientService.save(groupRecipient)) {
            return ResultVo.failure(ResultCode.FAILED);
        }
        return ResultVo.success();
    }

    /**
     * 收件人编辑
     *
     * @param recipient 收件人对象
     * @return 更新的收件人对象
     */
    @Override
    public ResultVo<Recipient> edit(Recipient recipient) {
        if (!this.updateById(recipient)) {
            return ResultVo.failure(ResultCode.FAILED);
        }
        return ResultVo.success();
    }

    /**
     * 收件人删除
     *
     * @param id 收件人Id
     * @return 删除成功或失败的结果及响应信息
     */
    @Override
    public ResultVo<Recipient> removeId(Integer id) {
        this.groupRecipientService.remove(Wrappers.<GroupRecipient>lambdaQuery().eq(GroupRecipient::getRecipientId, id));
        if (!this.removeById(id)) {
            return ResultVo.failure(ResultCode.FAILED);
        }
        return ResultVo.success();
    }

    /**
     * 根据分组Id查询收件人列表
     *
     * @param groupId 分组Id
     * @return 收件人列表
     */
    @Override
    public ResultVo<?> recipientListByGroupId(Long groupId) {
        List<Recipient> recipientList = this.list(getRecipientListByGroupId(groupId));
        return ResultVo.success(recipientList);
    }

    /**
     * 根据分组Id联表查询收件人列表的wrapper
     *
     * @param groupId 分组Id
     * @return 联表查询的wrapper
     */
    @Override
    public MPJLambdaWrapper<Recipient> getRecipientListByGroupId(Long groupId) {
        var wrapper = new MPJLambdaWrapper<Recipient>();
        wrapper.select(Recipient::getId, Recipient::getName, Recipient::getEmail, Recipient::getPhone)
                .leftJoin(GroupRecipient.class, GroupRecipient::getRecipientId, Recipient::getId)
                .eq(GroupRecipient::getGroupId, groupId);
        return wrapper;
    }

    /**
     * 收件人的导入
     *
     * @param file 导入的收件人excel表格
     * @return 导入的收件人列表
     * @throws IOException 导入异常处理
     */

    public ResultVo<?> importRecipients(MultipartFile file, Integer id) throws IOException {
        List<Recipient> dataList = new ArrayList<>();
        InputStream inputStream = file.getInputStream();
        Workbook workbook;

        // 根据文件名后缀选择Workbook实现
        String fileName = file.getOriginalFilename();
        if (Objects.requireNonNull(fileName).toLowerCase().endsWith(".xls")) {
            workbook = new HSSFWorkbook(inputStream); // 处理.xls文件
        } else if (fileName.toLowerCase().endsWith(".xlsx")) {
            workbook = new XSSFWorkbook(inputStream); // 处理.xlsx文件
        } else {
            return ResultVo.failure("不支持的文件格式");
        }

        try {
            Sheet sheet = workbook.getSheetAt(0);
            for (Row row : sheet) {
                if (row.getRowNum() > 0) { // 跳过标题行
                    // 检查是否为空行
                    boolean isEmptyRow = true;
                    for (Cell cell : row) {
                        if (cell != null && cell.getCellType() != CellType.BLANK) {
                            isEmptyRow = false;
                            break; // 找到非空单元格，标记行不为空
                        }
                    }
                    if (isEmptyRow) { // 如果是空行且之前已经找到过数据行，则停止读取
                        break;
                    }
                    // 如果此行非空，则处理数据
                    Recipient data = new Recipient();
                    String email = getCellValueAsString(row.getCell(0));
                    String name = getCellValueAsString(row.getCell(1));
                    String phone = getCellValueAsString(row.getCell(2));

                    data.setEmail(email);
                    data.setName(name);
                    data.setPhone(phone);
                    // 在这里进行数据校验
                    if (validateRecipient(data)) {
                        dataList.add(data);
                    }
                }
            }
            // 循环结束后，处理dataList,批量保存到数据库
            if (!dataList.isEmpty() && !this.saveBatch(dataList)) {
                return ResultVo.failure("数据保存失败");
            }
            List<GroupRecipient> groupRecipients = new ArrayList<>();
            dataList.addAll(repeatList);
            // 使用流操作去重并转换为列表
            List<Recipient> uniqueRecipients = dataList.stream()
                    .filter(Objects::nonNull)
                    .collect(Collectors.toMap(
                            Recipient::getEmail,
                            recipient -> recipient,
                            (existing, replacement) -> existing // 保留第一个出现的Recipient
                    ))
                    .values()
                    .stream()
                    .toList();

            for (Recipient recipient : uniqueRecipients) {
                GroupRecipient groupRecipient = new GroupRecipient();
                groupRecipient.setRecipientId(recipient.getId());
                groupRecipient.setGroupId(Long.valueOf(id));
                groupRecipients.add(groupRecipient);
            }
            List<Long> list = this.groupRecipientService.list(Wrappers.<GroupRecipient>lambdaQuery().eq(GroupRecipient::getGroupId, id))
                    .stream().map(GroupRecipient::getRecipientId).toList();
            List<GroupRecipient> toInsert = groupRecipients.stream()
                    .filter(recipient -> !list.contains(recipient.getRecipientId()))
                    .toList();
            if (!this.groupRecipientService.saveOrUpdateBatch(toInsert)) {
                return ResultVo.failure(ResultCode.IMPORT_FAILED);
            }
            return ResultVo.success();
        } finally {
            workbook.close();
            inputStream.close();
        }
    }

    /**
     * 读取单元格中的数据类型，并转换为String
     *
     * @param cell 表格表头
     */
    private String getCellValueAsString(Cell cell) {
        if (cell == null) {
            return null;
        }
        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                return String.format("%.0f", cell.getNumericCellValue());
            default:
                return null;
        }
    }

    /**
     * 数据校验
     *
     * @param recipient 收件人
     * @return 校验后的数据
     */
    private boolean validateRecipient(Recipient recipient) {
        // 检查邮箱格式是否正确
        if (recipient.getEmail() == null || !recipient.getEmail().contains("@")) {
            return false;
        }
        // 检查姓名是否为空
        if (recipient.getName() == null || recipient.getName().trim().isEmpty()) {
            return false;
        }
        Recipient recipient1 = this.getOne(new QueryWrapper<Recipient>().eq("email", recipient.getEmail()));
        // 检查邮箱是否重复
        if (recipient1 != null) {
            repeatList.add(recipient1);
            return false;
        }
        return true;
    }

    public void downloadTemplate(HttpServletResponse response) {
        OutputStream os;//新建一个输出流对象
        try {
            // 指定模板文件的位置
            String templateName = "download.xlsx";
            String basePath = System.getProperty("user.dir") + "/src/main/resources/static/pear/";//定义文件上传的根路径
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(templateName, StandardCharsets.UTF_8));
            response.setContentType("application/octet-stream");
            byte[] bytes = FileUtil.readBytes(basePath + templateName);//通过文件路径读取文件字节流
            os = response.getOutputStream();//通过输出流返回文件
            os.write(bytes);
            os.flush();
            os.close();
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }
}



